
#include "string.h"


PSTR tolower_self(PSTR str)
{
	int i = 0;

	for(; str[i]; i++)
	{
		if(str[i] >= 'A' && str[i] <= 'Z') 
			str[i] += 'a' - 'A';
	}

	return str;
}


PSTR toupper_self(PSTR str)
{
	int i = 0;

	for(; str[i]; i++)
	{
		if(str[i] >= 'a' && str[i] <= 'z') 
			str[i] += 'A' - 'a';
	}

	return str;
}


Sint32 stricmp(PCSTR dst, PCSTR src)
{
    CHAR f,l;
    
    do{
        if (((f = *(dst++)) >= 'A') && (f <= 'Z'))
            f -= ('A' - 'a');
        
        if (((l = *(src++)) >= 'A') && (l <= 'Z'))
            l -= ('A' - 'a');
    } while (f && (f == l));
    
    return (f - l);
}


PSTR trimleft(PSTR str)
{
	//SGL_ASSERT(FALSE && "NOT IMPLEMENTED YET!");
	return str;
}


PSTR trimright(PSTR str)
{
	//SGL_ASSERT(FALSE && "NOT IMPLEMENTED YET!");
	return str;
}


PSTR trim(PSTR str)
{
	//SGL_ASSERT(FALSE && "NOT IMPLEMENTED YET!");
	return str;
}


Sint32 split(PSTR str, CHAR sep, PSTR values[], Sint32 size)
{
	int i;	
	for(i = 0; i < size; i++)
	{
		while(*str && *str == sep) str++; //test space
		if(!*str) break;
		values[i] = str;
		while(*str && *str != sep) str++;
		if(!*str) return i+1;
		*str++ = 0;
	}	

	return i;
}


int32 wstrlen(PCWSTR str)
{
	int i = 0;
	if(!str) return 0;
	while(str[i] || str[i+1]) 
		i+=2;
	return i;
}


PWSTR wstrcpy(PWSTR dst, PCWSTR src)
{
	int i = 0;
	while(src[i] || src[i+1]) 
	{
		dst[i] = src[i];
		dst[i+1] = src[i+1];
		i+=2;
	}

	dst[i] = dst[i+1] = 0;
	return dst;
}


PWSTR wstrncpy(PWSTR dst, PCWSTR src, Sint32 size)
{
	int i = 0;
	size -= 2;

	while(src[i] || src[i+1]) 
	{
		if(i >= size) break;

		dst[i] = src[i];
		dst[i+1] = src[i+1];
		i+=2;
	}

	dst[i] = dst[i+1] = 0;
	return dst;
}


PCWSTR wstrchr(PCWSTR str, UCHAR chr1, UCHAR chr2)
{
	while(str[0] || str[1]) 
	{	
		if(str[0] == chr1 && str[1] == chr2)
			return str;
		str += 2;
	}
	
	return NULL;
}


Sint32 wstrcmp(PCWSTR str1, PCWSTR str2)
{
	while((str1[0] || str1[1]) && str1[0] == str2[0] && str1[1] == str2[1])
	{
		str1+=2; 
		str2+=2;
	}

	return str1[0]==str2[0]? str1[1]-str2[1] : str1[0]-str2[0];
}


PWSTR wtrimleft(PWSTR str)
{
	//SGL_ASSERT(FALSE && "NOT IMPLEMENTED YET!");
	return str;
}


PWSTR wtrimright(PWSTR str)
{
	//SGL_ASSERT(FALSE && "NOT IMPLEMENTED YET!");
	return str;
}


PWSTR wtrim(PWSTR str)
{
	int i;
	PWSTR porg = str;
	int len = wstrlen(str);

	//trim left
	for(;str[0] == 0 && str[1] == ' '; str += 2);

	//trim right
	for(i = len -1; porg[i -1] == 0 && porg[i] == ' '; i -= 2)
		porg[i] = 0;

	if(porg != str) wstrcpy(porg, str);

	return porg;
}


Sint32 str2wstr(PCSTR utf8, PWSTR unicode, Sint32 size)
{
	int i = 0, u = 0;
	
	SGL_MEMSET(unicode, 0, size); 
	while(utf8[i] && u < size - 2)
	{
		if((utf8[i] & 0x80) == 0)
		{
			// one byte 0...
			unicode[u+1] = utf8[i++];
		}else if((utf8[i] & 0x20) == 0){
			// two bytes 110... 10...
			unicode[u] = (UCHAR)((utf8[i]) & 0x1f) >> 2;
			unicode[u+1] = ((UCHAR)((utf8[i]) & 0x1f) << 6) | (utf8[i+1] & 0x3f);
			i+=2;
		}else{
			// three bytes 1110... 10... 10...
			unicode[u] = ((utf8[i] & 0x0f) << 4) | ((utf8[i+1] & 0x3f) >> 2);
			unicode[u+1] = (((utf8[i+1] & 0x3f) << 6)) | (utf8[i+2] & 0x3f);
			i+=3;
		}

		u+=2;
	}

	return u;
}


Sint32 wstr2str(PCWSTR unicode, PSTR utf8, Sint32 size)
{
	int u = 0, i = 0;

	SGL_MEMSET(utf8, 0, size);
	while((unicode[u] || unicode[u+1]) && i < size-1)
	{
		if(unicode[u] == 0 && unicode[u+1] < 128)
		{
			// 0 - 7 bits
			utf8[i++] = unicode[u+1];
		}else if((unicode[u] & 0xf8) == 0){
			// 8 - 11 bits
			utf8[i++] = 0xc0 | (unicode[u] << 2) | (unicode[u+1] >> 6);
			utf8[i++] = 0x80 | (unicode[u+1] & 0x3f);
		}else{
			// 12 - 16 bits
			utf8[i++] = 0xe0 | (unicode[u] >> 4);
			utf8[i++] = 0x80 | ((unicode[u] & 0x0f) << 2) | (unicode[u+1] >> 6);
			utf8[i++] = 0x80 | (unicode[u+1] & 0x3f);
		}

		u+=2;
	}
	
	return i;
}

////////////////////////////////////////////////////////////////////////////////
PWSTR wstrcat(PWSTR dst, PCWSTR src)
{
	int len = wstrlen(dst);
	return wstrcpy(dst + len, src);
}


#define LwChar(a)     (((a) >='A' &&  (a) <='Z')?a+0x20:a)

uint32 str2hash(PCSTR pcStrSource,int32 iLength)
{
    int32		iCount;	/*counter*/
    uint32		c0 = 0;
    uint32		c1 = 0;
    uint32		c2 = 0;
    uint32		c3 = 0;
	
    /*Check the input parameters*/
    if( NULL == pcStrSource || iLength <= 0 || (int32)mrc_strlen(pcStrSource)< iLength)
    {
        return 0;
    }
    iCount = iLength;
    /* This merge of a switch and a while statement is known
    * as "Duff's device", and is used for efficiency reasons. */
    switch (iLength & 0x3) 
    {
    case 0:
        while (iCount > 0)
		{
			--iCount;
			c3 ^= LwChar(pcStrSource[iCount]);
	case 3:
		--iCount;
		c2 ^= LwChar(pcStrSource[iCount]);
	case 2:
		--iCount;
		c1 ^=  LwChar(pcStrSource[iCount]);
	case 1:
		--iCount;
		c0 ^=  LwChar(pcStrSource[iCount]);
        }
    default:
        break;
    }
    
    return (((uint32)c0) << 24) | (((uint32)c1) << 16) |
        (((uint32)c2) <<  8) | ((uint32)c3);
}

